using System;
using System.Runtime.Serialization;
using System.Security.Cryptography;

namespace SharpObjects.Cryptography.DigitalSignature
{
	[Serializable]
	public class DsaKey : ICryptoKey
	{
		protected DSAParameters m_params;

		public DsaKey()
		{
		}

		public DsaKey(DSAParameters parameters)
		{
			m_params = parameters;
		}

		public DSAParameters GetParameters()
		{
			return m_params;
		}

		public static implicit operator DSAParameters(DsaKey key)
		{
			return key.GetParameters();
		}

		//#region ISerializable Members

		public DsaKey(SerializationInfo info, StreamingContext context)
		{
			m_params.Counter = (int)info.GetValue("m_params.Counter", typeof(int));
			m_params.G = (byte [])info.GetValue("m_params.G", typeof(byte []));
			m_params.J = (byte [])info.GetValue("m_params.J", typeof(byte []));
			m_params.P = (byte [])info.GetValue("m_params.P", typeof(byte []));
			m_params.Q = (byte [])info.GetValue("m_params.Q", typeof(byte []));
			m_params.Seed = (byte [])info.GetValue("m_params.Seed", typeof(byte []));
			m_params.X = (byte [])info.GetValue("m_params.X", typeof(byte []));
			m_params.Y = (byte [])info.GetValue("m_params.Y", typeof(byte []));
		}

		public void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			info.AddValue("m_params.Counter",  m_params.Counter);
			info.AddValue("m_params.G",  m_params.G);
			info.AddValue("m_params.J",  m_params.J);
			info.AddValue("m_params.P",  m_params.P);
			info.AddValue("m_params.Q",  m_params.Q);
			info.AddValue("m_params.Seed",  m_params.Seed);
			info.AddValue("m_params.X",  m_params.X);
			info.AddValue("m_params.Y",  m_params.Y);

		}

		//#endregion

		public override bool Equals(object obj)
		{
			DsaKey key = (DsaKey)obj;

			if(key.GetParameters().Counter != m_params.Counter)
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().G, m_params.G))
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().J, m_params.J))
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().Seed, m_params.Seed))
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().X, m_params.X))
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().Y, m_params.Y))
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().P, m_params.P))
			{
				return false;
			}

			if(!AreEqual(key.GetParameters().Q, m_params.Q))
			{
				return false;
			}

			return true;

		}

		protected bool AreEqual(byte [] arr1, byte [] arr2)
		{
			if(arr1 == null && arr2 == null)
			{
				return true;
			}

			if((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null))
			{
				return false;
			}

			if(arr1.Length != arr2.Length)
			{
				return false;
			}

			for(int k = 0; k < arr1.Length; k++)
			{
				if(arr1[k] != arr2[k])
				{
					return false;
				}
			}

			return true;
		}

		public static bool operator == (DsaKey key1, DsaKey key2)
		{
			return key1.Equals(key2);
		}

		public static bool operator != (DsaKey key1, DsaKey key2)
		{
			return ! key1.Equals(key2);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode ();
		}

	}
}
